package com.cartel.genius.services.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.cartel.genius.dao.CategoryDAO;
import com.cartel.genius.dao.exceptions.CategoryExistsException;
import com.cartel.genius.dao.exceptions.CategoryNotFoundException;
import com.cartel.genius.dao.exceptions.CategoryParentNotFoundException;
import com.cartel.genius.dto.CategoryTO;
import com.cartel.genius.services.CategoryService;
import com.mysql.jdbc.StringUtils;

/**
 * Service implementation class for Category (place divisions) operations
 * 
 * @author Naresh Reddy
 */
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class, RuntimeException.class })
public class CategoryServiceImpl implements CategoryService {
	
	private static final Logger logger = LoggerFactory.getLogger(CategoryServiceImpl.class);
	
	private CategoryDAO categoryDAO = null;	

	public void setCategoryDAO(CategoryDAO categoryDAO) {
		this.categoryDAO = categoryDAO;
	}
	
	/**
	 * Method to add root level category. All other categories will be childs of this category.
	 * 
	 * @param categoryName
	 * @return CategoryEntity
	 * @throws CategoryExistsException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public CategoryTO addRootCategory(String categoryName) throws CategoryExistsException {
		logger.debug("Entered [addRootCategory] of [CategoryServiceImpl]");
		
		// null and empty check of category name
		if (StringUtils.isNullOrEmpty(categoryName)) {
			logger.warn("Category name is null or empty");
			throw new IllegalArgumentException("Category name is null or empty");
		}
		CategoryTO categoryTO = categoryDAO.addRootCategory(categoryName);
		
		logger.debug("Exiting [addRootCategory] of [CategoryServiceImpl]");
		
		return categoryTO;
	}
	
	/**
	 * Method to add child category under specified parent
	 * 
	 * @param categoryName
	 * @param parentCategory
	 * @return CategoryEntity
	 * @throws CategoryExistsException
	 */
	private CategoryTO addCategory(String categoryName, CategoryTO parentCategory) throws CategoryExistsException, CategoryParentNotFoundException {
		logger.debug("Entered [addCategory] of [CategoryServiceImpl]");
		
		// null check parentCategory and either parent category name or category id should be present
		if (parentCategory == null || StringUtils.isNullOrEmpty(categoryName) || (StringUtils.isNullOrEmpty(parentCategory.getCategoryName()) && parentCategory.getCategoryId() == 0)) {
			logger.warn("Parent category is null");
			throw new IllegalArgumentException("Parent category is null");
		}
		
		CategoryTO addedCategory = categoryDAO.addCategory(categoryName, parentCategory);		
		logger.debug("Exiting [addCategory] of [CategoryServiceImpl]");
		
		return addedCategory;
	}
	
	/**
	 * Method to add child category under specified parent
	 * 
	 * @param categoryName
	 * @param parentCategory
	 * @return CategoryEntity
	 * @throws CategoryExistsException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public CategoryTO addCategory(String categoryName, Integer parentCategoryId) throws CategoryExistsException, CategoryParentNotFoundException {
		if (parentCategoryId == 0) {
			logger.warn("Illegal parent id " + parentCategoryId);
			throw new IllegalArgumentException("Illegal parent id");
		}
		
		if (StringUtils.isNullOrEmpty(categoryName)) {
			logger.warn("Illegal category name");
			throw new IllegalArgumentException("Illegal category name");
		}
		CategoryTO categoryTO = new CategoryTO();
		categoryTO.setCategoryId(parentCategoryId);
		
		return addCategory(categoryName, categoryTO);
	}
	
	/**
	 * Method to add child category under specified parent
	 * 
	 * @param categoryName
	 * @param parentCategory
	 * @return CategoryEntity
	 * @throws CategoryExistsException
	 */
	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public CategoryTO addCategory(String categoryName, String parentCategoryName) throws CategoryExistsException, CategoryParentNotFoundException {
		if (StringUtils.isNullOrEmpty(parentCategoryName)) {
			logger.warn("Illegal parent category name");
			throw new IllegalArgumentException("Illegal parent category name");
		}
		
		if (StringUtils.isNullOrEmpty(categoryName)) {
			logger.warn("Illegal category name");
			throw new IllegalArgumentException("Illegal category name");
		}
		CategoryTO categoryTO = new CategoryTO();
		categoryTO.setCategoryName(parentCategoryName);
		
		return addCategory(categoryName, categoryTO);
	}

	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public CategoryTO modifyCategory(String categoryName, int oldParentId, int newParentId) throws CategoryNotFoundException, CategoryParentNotFoundException {
		// TODO
		throw new UnsupportedOperationException();
	}

	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public boolean removeCategory(int categoryId) throws CategoryNotFoundException {
		// TODO
		throw new UnsupportedOperationException();
	}

	@Override
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public boolean removeCategory(String categoryName) throws CategoryNotFoundException {
		// TODO
		throw new UnsupportedOperationException();
	}		

}
